import { Throwable } from "../err_handle/throwable"
import { isPromise, promisic } from "../utils/utils.js"

/**
 * 错误提示状态码
 */
export const errTips = {
	"301": "永久重定向",
	"400": "请求包含不支持的参数",
	"401": "未授权",
	"403": "禁止访问",
	"404": "请求的资源不存在",
	"405": "不支持的请求方式",
	"413": "上传的文件体积太大",
	"500": "服务器内部错误",
	"502": "服务器异常",
	
	"10000": "发生了一个未知错误，请联系管理员进行处理",
	"10001": "请求出错",
	"10002": "未注册",
	"10003": "未登录",
	"10004": "请选择公司",
	"10005": "暂无对应精选服务",
	
	"600000": "未知的网络错误",
	"600001": ""
}

/**
 * 打印网络请求参数，请求方式、请求url、请求头、请求体
 */
const debugRequestParams = function(url, method = "GET", path = {}, query = {}, data = {}, header = {}) {
	let queryStr = ""
	if(query) {
		for(let key in query) {
			queryStr += key + "=" + encodeURIComponent(query[key]) + "&"
		}
		if(queryStr.endsWith("&")) {
			queryStr = queryStr.substring(0, queryStr.lastIndexOf("&"))
		}
	}
	
	let newUrl = url
	if(path) {
		for(let key in path) {
			newUrl = newUrl.replaceAll("{" + key + "}", path[key]);
		}
	}
	
	newUrl =  newUrl + (queryStr ? ("?" + queryStr):"")
	
	let bodyStr = ""
	if(data) {
		for(let key in data) {
			bodyStr += key + "=" + encodeURIComponent(data[key]) + "&"
		}
		if(bodyStr.endsWith("&")) {
			bodyStr = bodyStr.substring(0, bodyStr.lastIndexOf("&"))
		}
	}
	
	console.debug("----- interceptorRequest -----")
	console.debug(method + " ", newUrl)
	console.debug("header ", Object.assign({"content-type": "application/json"}, header))
	if(method === "GET") {
		return
	}
	if(header["content-type"] === 'application/x-www-form-urlencoded') {
		console.debug("body ", bodyStr)
	} else {
		console.debug("body ", data)
	}
	console.debug("----- interceptorRequest -----")
}

/**
 * 打印网络请求返回结果
 */
const debugResponse = function(data) {
	console.debug("----- interceptorResponse -----")
	console.debug("response ", data)
	console.debug("----- interceptorResponse -----")
}

/** 
 * 校验并更新登录状态:
 * 1.在业务层请求网络之前执行
 *
 * 2.未注册，抛出一个Error(10002, "未注册")，待应用捕获到之后，自动跳转授权页
 * 
 * 3.已注册，如果在config.js中为Http类配置了checkLogin方法，
 * 则调用checkLogin去校验登录状态，如果登录失效，会抛出Error(10003, "未登录")
 * 在该方法中会捕获Error(10003, "未登录")，捕获到之后，进行登录状态的刷新，
 * 最后执行业务层请求网络的代码
 * 
 * 4.已注册，未在config.js中为Http类配置了checkLogin方法，默认会认为不校验登录态，
 * 接下来会执行业务层请求网络的代码
 * 
 * 5.当进行登录状态的刷新时，如果在config.js中为Http类配置了login方法，则调用login方法，
 * 重新获取新的token，也就是code2token的流程，并更新本地缓存中token，保证后续业务取到
 * 最新有效的token
 * 
 * 6.当进行登录状态的刷新时，未在config.js中为Http类配置了login方法，则会抛出Error(10003, "未登录")
 * 待应用捕获到之后，也会自动跳转授权页
 */
export const updateLoginStatus = function(http) {
	let checkLoginPromise = http["checkLogin"]()
	if(isPromise(checkLoginPromise)) {
		return checkLoginPromise
	} else {
		return Promise.resolve()
	}
}

/**
 * 1.拦截业务层网络请求，在请求之前校验并更新登录状态，
 * 具体实现请看updateLoginStatus方法
 */
export const interceptorRequest = function(author, http) {
	if(author) {
		if(http && http["checkLogin"]) {
			return updateLoginStatus(http)
		} else {
			return Promise.resolve()
		}
	} else {
		return Promise.resolve()
	}
}

/**
 * 业务层网络请求成功后，如果是未登录的情况，会刷新登录态，并重新执行该次请求
 */
export const interceptorResponse = function(reason, fun, http, autoUpdateLogin) {
	if(reason.code === 10003) {
		//未登录，无感刷新token
		if(http && http["login"] && autoUpdateLogin) {
			return promisic(uni.login)({provider: "weixin"})
				.then(res => {
					let loginPromise = http["login"](res.code)
					if(isPromise(loginPromise)) {
						return loginPromise.then(res => {
							if(fun) {
								return fun()
							} else {
								return Promise.resolve()
							}
						})
					} else {
						return Promise.reject(reason)
					}
				})
		} else {
			return Promise.reject(reason)
		}
	} else {
		return Promise.reject(reason)
	}
}